import os, subprocess
import random, string
import filecmp
# import time
from tkinter import *
from tkinter.filedialog import askopenfilename, askopenfilenames, askdirectory, asksaveasfilename
import tkinter.messagebox as messagebox

import zipfile


def AllFileList(folder, fileList):
    try:
        fl=os.listdir(folder)
    except Exception as ex:
        fl=[]
    for fn in fl:
        path=os.path.join(folder,fn)
        if os.path.isfile(path):
            fileList.append(path)
            print('file '+path)
        elif os.path.isdir(path):
            AllFileList(path, fileList)
        else:
            print('unknown type '+path)

def AllFileListA(folder):
    fl=[]
    AllFileList(folder, fl)
    return fl

def AllFileListB(folder):
    fl=AllFileListA(folder)
    n=len(folder)
    if folder[-1]!='/' and folder[-1]!='\\':
        n+=1
    return [ fni[n:] for fni in fl ]

def fsync(oldpath, newpath):
    flOld=AllFileListB(oldpath)
    flNew=AllFileListB(newpath)
    # print(str(flOld))
    # print(str(flNew))
    delList=list(set(flOld).difference(set(flNew)))
    # print(str(delList))
    addList=[]
    for fni in flNew:
        newp=os.path.join(newpath, fni)
        oldp=os.path.join(oldpath, fni)
        if os.path.exists(oldp) and filecmp.cmp(newp,oldp):
            print('duplicate file '+fni)
        else:
            addList.append(fni)
    # print(str(addList))
    return delList, addList
    
def zipp(path, newpath, flist):
    zp=zipfile.ZipFile(path,'w', zipfile.ZIP_DEFLATED)
    for file in flist:
        zp.write(os.path.join(newpath, file), file)
    zp.close()

def update_pack(oldpath, newpath, outzip):
    delp, addp=fsync(oldpath, newpath)
    print('remove list='+str(delp))
    print('add list='+str(addp))
    folder, name=os.path.split(outzip)    

    zp=zipfile.ZipFile(outzip,'w', zipfile.ZIP_DEFLATED)

    if len(addp)>0:
        addzip=os.path.join(folder, '+.zip')
        zipp(addzip, newpath, addp)
        zp.write(addzip, '+.zip')
        os.remove(addzip)
        
    if len(delp)>0:
        removetxt=os.path.join(folder, '-.txt')
        with open(removetxt, 'w', encoding='utf-8') as f:
            for deli in delp:
                f.write(deli+'\n')
        zp.write(removetxt, '-.txt')
        os.remove(removetxt)
        
    zp.close()


def update_from_pack(uppath, zippath):
    folder, ext=os.path.splitext(zippath)    
    if os.path.exists(folder):
        print(folder+' exists, delete it and try again')
    else:
        zp=zipfile.ZipFile(zippath)
        zp.extractall(folder)
        zp.close()
        if os.path.exists(folder):
            removetxt=os.path.join(folder, '-.txt')
            if os.path.exists(removetxt):
                with open(removetxt, 'r') as f:
                    badl=f.readlines()
                    delp=[line[0:-1] for line in badl]        
                    for deli in delp:
                        upi=os.path.join(uppath, deli)
                        if os.path.exists(upi):
                            os.remove(upi)
                            print('remove file '+deli)
                os.remove(removetxt)
            addzip=os.path.join(folder, '+.zip')
            if os.path.exists(addzip):
                print('add file from '+addzip)
                zp=zipfile.ZipFile(addzip)
                zp.extractall(uppath)
                zp.close()
                os.remove(addzip)
            os.rmdir(folder)
    
class Application(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()
        self.createWidgets()

    def createWidgets(self):
        self.nameInput = Entry(self, width=200)
        self.nameInput.pack()
        self.alertButton = Button(self, text='old version', command=self.setOld, height=2, width=6)
        self.alertButton.pack()
        self.nameInput2 = Entry(self, width=200)
        self.nameInput2.pack()
        self.alertButton2 = Button(self, text='new version', command=self.setNew, height=2, width=6)
        self.alertButton2.pack()
        self.nameInput3 = Entry(self, width=200)
        self.nameInput3.pack()
        self.alertButton6 = Button(self, text='zip path', command=self.setZip, height=2, width=8)
        self.alertButton6.pack()
        self.alertButton4 = Button(self, text='make zip', command=self.makezip, height=2, width=20)
        self.alertButton4.pack()
        self.alertButton7 = Button(self, text='update old', command=self.update, height=2, width=20)
        self.alertButton7.pack()
        
    def setZip(self):
        fd=askopenfilename()
        self.nameInput3.delete(0, 'end')
        self.nameInput3.insert(0, fd)
        
    def setOld(self):   
        fd=askdirectory()
        self.nameInput.delete(0, 'end')
        self.nameInput.insert(0, fd)
        
    def setNew(self):
        fd=askdirectory()
        self.nameInput2.delete(0, 'end')
        self.nameInput2.insert(0, fd)
        
    def makezip(self):
        oldp = self.nameInput.get()
        newp = self.nameInput2.get()
        uzip = self.nameInput3.get()
        update_pack(oldp, newp, uzip)
        messagebox.showinfo('complete', 'make zip %s' % uzip)

    def update(self):
        oldp = self.nameInput.get()
        uzip = self.nameInput3.get()
        update_from_pack(oldp, uzip)
        messagebox.showinfo('complete', 'update %s' % oldp)
    
if __name__=='__main__':
    print(sys.argv)
    if len(sys.argv)==5 and sys.argv[1]=='p':
        oldp=sys.argv[2]
        newp=sys.argv[3]
        uzip=sys.argv[4]
        update_pack(oldp, newp, uzip)
    elif len(sys.argv)==4 and sys.argv[1]=='u':
        oldp=sys.argv[2]
        uzip=sys.argv[3]
        update_from_pack(oldp, uzip)
    else:
        app = Application()
        app.master.title('update tool')
        app.mainloop()

